#ifndef GAMEFRAMEWORK_SOUND_H_
#define GAMEFRAMEWORK_SOUND_H_

#include <mad.h> // extern library

#include "path.h"
#include "log.h"
#include "audio.h"




class Sound
{
  /* Enum */
private:
  enum PlayState {
    SOUND_PLAY,
    SOUND_PAUSE,
    SOUND_STOP
  };

  /* struct */
private:
  struct Buffer {
    unsigned char const *start;
    unsigned long length;
    Sound* instance;
  };

  /* Static */

private:

    /* MP3 decode function */

  static mad_flow input(void *data,
      mad_stream *stream);
  
  static mad_flow error(void *data,
      mad_stream *stream,
      mad_frame *frame);
  
  static mad_flow output(void *data,
      const mad_header *header,
      mad_pcm *pcm);

  static signed int scale(mad_fixed_t &sample);

public:
  static int WINAPI DecodeCallback(void* pInstance);

  /* Constructor, destructor */

public:
  Sound(void);
  Sound(LPWSTR fileName, Audio *audio);
  ~Sound(void);
public:
  void Play(bool loop);
  void Pause();
  void Stop();
private: 
  /* Instance method replace for static */
  mad_flow InstanceOutput (
      void *data,
      const mad_header *header, mad_pcm *pcm);
  void Prepare();
  void WriteBuffer(mad_pcm *pcm);
  void WriteData(LPBYTE lpData, // pointer to input buffer
    DWORD dwOffSet, // offset of directsound buffer begin write
    DWORD dwSoundByte); // size want to write 
  int Decode();

  /* member variable */
private:
  

  LPWSTR fileName;
  LPDIRECTSOUNDBUFFER8 buffer8;
  Audio *audio;
  int bufferSize;
  HANDLE threadHandle; // thread handle
  HANDLE fileHandle; // sound file handle
  HRESULT hResult;
  LPVOID mapPointer;
  unsigned long fileLength;
  
  // Fill buffer control member
  //
  DWORD playPos;
  DWORD writePos;
  DWORD prevPlayPos;
  bool firstFillBuffer;

  // Playback control member
  //
  bool loop;
  enum PlayState playState;
};

#endif // GAMEFRAMEWORK_SOUND_H_